package com.df.ez_game.net;

import com.df.ez_game.tools.OsHelper;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import java.util.function.Consumer;

public class TcpConnector extends Thread implements Connector {
    // 状态常量
    private static final int STATE_INIT = 0;      // 初始状态
    private static final int STATE_STARTING = 2;  // 线程启动
    private static final int STATE_CONNECTED = 3;  // 连接成功
    private static final int STATE_CONNECTING = 4; // 连接中
    private static final int STATE_CLOSED = 5;     // 已关闭
    
    // 连接状态监听器
    private volatile Consumer<Boolean> connectListener;

    private final String ip;
    private final int port;
    private final AtomicInteger status = new AtomicInteger(STATE_INIT);
    private final Set<ChannelHandler> handlers = new HashSet<>();
    private final int maxRetryTimes; // -1=无限重试, 0=不重试, >0=最大重试次数
    private final long retryIntervalMs; // 重试间隔(毫秒)

    private volatile Channel activeChannel;
    private volatile EventLoopGroup eventLoopGroup;
    private volatile boolean running = true;

    public TcpConnector(String ip, int port, int maxRetryTimes, long retryIntervalMs) {
        this.ip = ip;
        this.port = port;
        this.maxRetryTimes = maxRetryTimes;
        this.retryIntervalMs = retryIntervalMs;
    }

    @Override
    public EventLoopGroup getEventloopgroup() {
        if (eventLoopGroup == null) {
            eventLoopGroup = OsHelper.getGroupByOs();
        }
        return eventLoopGroup;
    }

    @Override
    public void addInHandler(ChannelHandler handler) {
        handlers.add(handler);
    }

    @Override
    public void addOutHandler(ChannelHandler handler) {
        handlers.add(handler); // 修复：原代码错误地使用remove
    }
    
    @Override
    public void setConnectListener(Consumer<Boolean> listener) {
        this.connectListener = listener;
    }

    @Override
    public void run() {
        if (!status.compareAndSet(STATE_INIT, STATE_STARTING)) {
            throw new IllegalStateException("Connector already started");
        }

        while (running && shouldRetry(0)) {
            connect();
            // 等待重试间隔
            if (running && status.get() != STATE_CONNECTED) {
                try {
                    Thread.sleep(retryIntervalMs);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }

    @Override
    public void connect() {
        // 状态检查
        if (!status.compareAndSet(STATE_STARTING, STATE_CONNECTING) &&
                !status.compareAndSet(STATE_CLOSED, STATE_CONNECTING)) {
            return;
        }

        // 参数验证
        if (ip == null || port <= 0) {
            throw new IllegalArgumentException("Invalid IP or port");
        }

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(getEventloopgroup())
                    .channel(NioServerSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            //协议编解码
                            ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
                                    5*1024*1024,
                                    // 长度字段的偏移量， 不偏移
                                    0,
                                    // 字段的长度,
                                    4,
                                    // 要添加到长度字段值的补偿值：长度调整值 = 内容字段偏移量 - 长度字段偏移量 - 长度字段的字节数
                                    0,
                                    // 跳过的初始字节数： 跳过0位; (跳过消息头的 0 位长度)
                                    0));
                            // 添加心跳检测 (5秒写空闲时发送心跳)
                            ch.pipeline().addLast("idleStateHandler",
                                    new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));

                            // 添加自定义处理器
                            for (ChannelHandler handler : handlers) {
                                ch.pipeline().addLast(handler);
                            }

                            // 添加连接状态监听器
                            ch.pipeline().addLast(new ConnectionStateHandler());
                        }
                    });

            // 连接操作
            ChannelFuture future = bootstrap.connect(ip, port).sync();
            activeChannel = future.channel();

            future.addListener((ChannelFutureListener) f -> {
                if (f.isSuccess()) {
                    if (status.compareAndSet(STATE_CONNECTING, STATE_CONNECTED)) {
                        onConnected(f.channel());
                    }
                } else {
                    handleConnectFailure(f.cause(), 0);
                }
            });
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            handleConnectFailure(e, 0);
        } catch (Exception e) {
            handleConnectFailure(e, 0);
        }
    }


    private void handleConnectFailure(Throwable cause, int retryCount) {
        status.set(STATE_STARTING);
        onError(null, new Exception("Connection failed", cause));
        
        // 触发连接失败监听
        if (connectListener != null) {
            connectListener.accept(false);
        }

        // 关闭可能残留的资源
        if (activeChannel != null) {
            activeChannel.close();
            activeChannel = null;
        }
    }

    private boolean shouldRetry(int currentRetryCount) {
        if (!running) return false;
        return maxRetryTimes == -1 ||
                (maxRetryTimes > 0 && currentRetryCount < maxRetryTimes);
    }

    @Override
    public void onConnected(Channel channel) {
        // 启动心跳检测等操作
        System.out.println("Connected to server: " + channel.remoteAddress());
        // 触发连接成功监听
        if (connectListener != null) {
            connectListener.accept(true);
        }
        // TODO: 发送注册信息
    }

    @Override
    public void onError(Channel channel, Exception e) {
        System.err.println("Connection error: " + e.getMessage());
        e.printStackTrace();
        // 处理业务逻辑异常
    }

    @Override
    public void sendMsg(byte[] data) {
        if (status.get() != STATE_CONNECTED || activeChannel == null) {
            throw new IllegalStateException("Not connected");
        }

        ChannelFuture future = activeChannel.writeAndFlush(data);
        future.addListener((ChannelFutureListener) f -> {
            if (!f.isSuccess()) {
                onError(f.channel(), new Exception("Send failed", f.cause()));
                handleDisconnection();
            }
        });
    }

    public void shutdown() {
        running = false;
        status.set(STATE_CLOSED);

        if (activeChannel != null) {
            activeChannel.close();
        }

        if (eventLoopGroup != null) {
            eventLoopGroup.shutdownGracefully();
        }

        interrupt(); // 中断重试循环
    }

    private void handleDisconnection() {
        if (status.compareAndSet(STATE_CONNECTED, STATE_STARTING)) {
            if (activeChannel != null) {
                activeChannel.close();
                activeChannel = null;
            }
            // 自动触发重连 (由run循环处理)
        }
    }

    /**
     * 内部处理器用于监听连接状态变化
     */
    private class ConnectionStateHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            System.out.println("Connection lost");
            handleDisconnection();
            ctx.fireChannelInactive();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            onError(ctx.channel(), new Exception("Channel error", cause));
            ctx.close();
            handleDisconnection();
        }

        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
            // 心跳检测处理 (需实现具体心跳协议)
            // if (evt instanceof IdleStateEvent) {
            //     sendHeartbeat(ctx.channel());
            // }
        }
    }
}
